v4#97
Merged
Merged
Conversation
Merge pull request #72 from propublica/develop
…stic ColumnDef[] system (#75) * docs: add recipe prep redesign — design doc + implementation plan Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: replace named-field PrepRecipeParams/Result with agnostic ColStrategy shapes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: update stale JSDoc comments in shared/types.ts after PrepRecipeResult simplification Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: rewrite prepRecipe() to iterate PrepColSpec[] with two-pass folder scan Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: replace named-field RecipeParams with ColumnDef[] + RecipeSettings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: update google.d.ts prepRecipe return type, move ToolId import, update services test shapes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: migrate document-summarization recipe to ColumnDef[] shape Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: rewrite RecipePanel tests for ColumnDef[] shape (failing — panel rewrite in next task) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: consolidate recipes.ts imports, remove unused mount() return field, add empty-appendField test Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: rewrite RecipePanel for ColumnDef[] — agnostic column specs, role-based RunConfig assembly Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * style: apply Prettier formatting to recipe.ts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * style: fix Prettier formatting in server/index.ts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Exports CHUNK_SIZE (50) and computeChunks() from ConfigureAIRunPanel module so handleRun() can slice row ranges into fixed-size batches for chunked execution. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace single runBatchAI dispatch with a chunked async loop that shows a confirmation dialog for large row counts and respects jobStore.isCancelled() between chunks. Falls back to single dispatch when no explicit rowRange is set. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…#77) * feat: add cancelling to LoadingStatus Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add cancel, isCancelled, setProgress to JobStore Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add computeChunks helper with tests Exports CHUNK_SIZE (50) and computeChunks() from ConfigureAIRunPanel module so handleRun() can slice row ranges into fixed-size batches for chunked execution. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: pre-flight warning and chunked dispatch in handleRun Replace single runBatchAI dispatch with a chunked async loop that shows a confirmation dialog for large row counts and respects jobStore.isCancelled() between chunks. Falls back to single dispatch when no explicit rowRange is set. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: inline runChunks IIFE and clarify chunk warning guard Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: stop button and cancelling state in JobIndicator Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: escape double quotes in JobIndicator HTML attribute * docs: add chunked batch execution design and implementation plan * fix: prevent poll from overwriting cancelling state; reduce chunk size to 10; clarify cancel message * feat: show global row range between chunks; surface row progress when cancelling - Between-chunk progress now shows "Rows X–Y of Z" using sheet row numbers instead of abstract chunk numbers, giving users global context - When cancelling, server polling message is passed through as "Stopping — {message}" so users can see how far the current chunk has to go - Reduce CHUNK_SIZE to 10 rows for more responsive cancellation (was 50) - Add test covering the "Stopping —" message passthrough behavior Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: hint in row range label that explicit range enables large-job features Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: move row range hint to sit next to "Specify range" radio option Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add cancelling to LoadingStatus Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add cancel, isCancelled, setProgress to JobStore Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add computeChunks helper with tests Exports CHUNK_SIZE (50) and computeChunks() from ConfigureAIRunPanel module so handleRun() can slice row ranges into fixed-size batches for chunked execution. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: pre-flight warning and chunked dispatch in handleRun Replace single runBatchAI dispatch with a chunked async loop that shows a confirmation dialog for large row counts and respects jobStore.isCancelled() between chunks. Falls back to single dispatch when no explicit rowRange is set. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: inline runChunks IIFE and clarify chunk warning guard Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: stop button and cancelling state in JobIndicator Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: escape double quotes in JobIndicator HTML attribute * docs: add chunked batch execution design and implementation plan * fix: address post-review issues from chunked batch execution feature - setProgress() now guards against overwriting cancelling state - Align cancel message wording: all cancelling messages use "Stopping — ..." prefix - Extract chunk loop from handleRun() into private runChunks() method - Document estimatedMins 5s/row assumption with inline comment - Fix isCancelled test that was checking the wrong job ID; add dedicated test for cancel flag cleanup on job completion Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: replace SingleTagList/TagList column pickers with TokenInput * feat: make new-column chip prefix configurable via newDefault option Add newDefault to TokenInputOpts so each panel can pre-fill the new-column chip with a contextually appropriate name. ai_ for AI output, extracted_text for Extract Text, drive_links for Import Drive Links. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com
…igureAIRunPanel (#79) * docs: add PromptColList UI design for ordered prompt column selection * feat: add PromptColList component for ordered prompt column selection Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: clarify moveRow variable names in PromptColList * feat: add pcol-* styles for PromptColList component Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: replace split TokenInput pickers with PromptColList in ConfigureAIRunPanel Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: update configure-ai-run tests for PromptColList Replace old user-prompt-cols/drive-file-cols field ID helpers with new addPromptCol/getPromptColValues helpers that interact with the PromptColList component's .pcol-row/.pcol-add-btn DOM structure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: add PromptColList unit tests and implementation plan Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: add PromptColList UI design for ordered prompt column selection * feat: reduce OAuth scopes to least-privilege for Drive access Replaces the broad `drive` scope with `drive.readonly` + `drive.file`, removing "edit and delete all your Google Drive files" from the consent screen. Adds user-facing auth model documentation and implementation design doc. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * removing old auth model doc
Bumps [hono](https://github.com/honojs/hono) from 4.12.8 to 4.12.12. - [Release notes](https://github.com/honojs/hono/releases) - [Commits](honojs/hono@v4.12.8...v4.12.12) --- updated-dependencies: - dependency-name: hono dependency-version: 4.12.12 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* docs: add ConfigureAIRunPanel UX redesign design doc * refactor: collapse PromptColList row to single inline line * feat: reorder ConfigureAIRunPanel sections and add helper text * fix: remove duplicate field-helper CSS rule * feat: add collapsible Tools section to ConfigureAIRunPanel * docs: add ConfigureAIRunPanel UX redesign implementation plan * fix: prevent collapsible header overflow with min-width and box-sizing * fix: prevent sidebar horizontal overflow from collapsible header and prompt row * fix: prevent sidebar horizontal overflow from collapsible header and prompt row * refactor: replace kind pills with cycling toggle in PromptColList * feat: add cycle indicator to kind toggle and tighten row spacing * feat: move Tools section above Rows to process * feat: add divider lines between panel sections
* feat: prepend label to text parts in runInference when PromptInput.label is set Also redirects Jest cache to project-local .jest-cache/ so commits work in sandboxed environments. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add prefixWithColName to RunConfig and forward label in runBatchAI Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add prefixWithColName checkbox to ConfigureAIRunPanel Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: add column label prefix design and implementation plan Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: move prefix checkbox under User Prompt Columns, shorten copy Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Bumps [@hono/node-server](https://github.com/honojs/node-server) from 1.19.11 to 1.19.13. - [Release notes](https://github.com/honojs/node-server/releases) - [Commits](honojs/node-server@v1.19.11...v1.19.13) --- updated-dependencies: - dependency-name: "@hono/node-server" dependency-version: 1.19.13 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps and [brace-expansion](https://github.com/juliangruber/brace-expansion). These dependencies needed to be updated together. Updates `brace-expansion` from 1.1.12 to 1.1.13 - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](juliangruber/brace-expansion@v1.1.12...v1.1.13) Updates `brace-expansion` from 5.0.3 to 5.0.5 - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](juliangruber/brace-expansion@v1.1.12...v1.1.13) --- updated-dependencies: - dependency-name: brace-expansion dependency-version: 1.1.13 dependency-type: indirect - dependency-name: brace-expansion dependency-version: 5.0.5 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…mplate (#87) * feat: add interpolateTemplate utility for recipe template strategy Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: update ColStrategy and PrepRecipeParams for inputId-based binding Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: update prepRecipe to resolve inputId refs and handle template strategy Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: replace ColumnDef cluster with UserInput; update RecipeDefinition Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: update recipes-list nav and services test for new RecipeDefinition and PrepRecipeParams shapes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: rewrite RecipePanel to render UserInput[] and use prepTemplate/runTemplate Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: rewrite RECIPES registry under new RecipeDefinition shape Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: prettier format utils.ts; add recipe redesign impl plan doc * adding planning doc * refactor: rename ColStrategy→FillStrategy and strategy→fillStrategy Consistent naming across all layers: the discriminated union is now FillStrategy (it describes how a column gets filled at prep time) and the field on PrepColSpec is fillStrategy. No behaviour change. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: derive RunConfig from column roles, drop runTemplate Each PrepColSpec now carries an optional role (file-prompt, text-prompt, system-prompt, output). RecipePanel builds the column-referencing parts of RunConfig via buildRunTemplate() instead of reading a manually-written runTemplate. Non-column AI settings move to RecipeDefinition.settings. RecipeDefinition.runTemplate removed — column titles now exist in exactly one place. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: simplify ColumnRole to string union, RecipeSettings to Pick ColumnRole had no payload on any variant — the object wrapper was unnecessary ceremony. Now a plain string union. RecipeSettings is now Pick<RunConfig, ...> so it tracks RunConfig automatically instead of duplicating field declarations. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: split PrepColSpec/RecipeColumn, rename UserInput→RecipeInput PrepColSpec (shared RPC type) no longer carries role — the server never reads it. RecipeColumn extends PrepColSpec client-side and adds role, keeping ColumnRole out of the RPC boundary. UserInput renamed to RecipeInput to make its scope explicit — it's a recipe-specific concept, not a generic form primitive. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add conditional block syntax to interpolateTemplate Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: add same-key block test; docs: note nesting unsupported Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: update document-summarization recipe for journalism use * test: integration tests for recipe template rendering * docs: add design and implementation plan for document summarization recipe redesign * feat: remove redundant User Prompt column from document-summarization recipe * feat: apply field-label styling and (optional) markers to recipe inputs * feat: use field-group wrapper for recipe inputs to get section dividers * feat: add intro field to RecipeDefinition for panel-level description * fix: remove redundant optional field guidance from recipe intro * tweaking helper text * fix: remove BLUF label prefix from system prompt structure guideline --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…#90) - Add TokenInput and PromptColList to CLAUDE.md component graph - Add Recipe System section to CLAUDE.md (RecipeDefinition shape, RecipeColumn.role, FillStrategy kinds including template syntax, RecipeInput.id naming constraint) - Fix stale recipe propagation path in Tool System section (server no longer echoes back RunConfig; preppedRunConfig is assembled client-side) - Add RunConfig / PromptColumnSpec section to architecture.md - Fix google.d.ts description to clarify only client-callable functions need declarations, not every server function - Update architecture.md recipes description to match new RecipeDefinition shape and correct preppedRunConfig assembly flow Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
) * feat: improve empty-state message in Run AI panel with recipes link Replaces the terse "No columns found" message with copy that points users to Recipes as a starting point, and wires a click handler to navigate directly to the recipes list. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * tweaking helper text --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Make the typefaces better match Google Sheets.
Documents font size tokens, font-family rule for form elements, and preferred color variables introduced in the #92 style standardization PR. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: AI processing redesign — parallel real-time and async batch paths Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: add Phase 1 + Phase 2 AI processing redesign design docs Phase 1 spec covers parallel fetchAll pipeline, Files API integration, and inference.ts refactor. Phase 2 notes park the async batch API design for a future planning session. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: add Phase 1 parallel inference pipeline implementation plan Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add callGeminiAPIBatch for parallel Gemini inference * feat: add fetchDriveMetadata and downloadDriveFiles for parallel Drive access * feat: add uploadFilesToGemini for Gemini Files API integration Implements parallel file upload to the Gemini Files API using UrlFetchApp.fetchAll with multipart/related encoding, batched in groups of 10 to limit peak memory pressure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: extract buildInferenceRequest from runInference for batch path Splits the request-building logic out of runInference into a new exported buildInferenceRequest function. This pure builder accepts an optional fileUriMap (Files API URI path) alongside the existing inline_data fallback, making it usable by the upcoming runBatchAI batch path without duplicating Drive-encoding logic. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: replace sequential runBatchAI loop with parallel fetchAll pipeline Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: increase chunk size to 50 rows and update warning dialog for parallel execution * test: add coverage threshold for files.ts * fix: use exported mimeType (not Drive native) when uploading Workspace files to Gemini * test: add missing coverage tests for callGeminiAPIBatch codePairs and drive error branches * feat: include row range in batch AI progress messages Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: add supportsAllDrives=true to Drive API v3 requests Without this parameter, the Drive REST API silently returns 404 for files in shared drives (Team Drives), even when the user has access. DriveApp handles this transparently; raw REST calls do not. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: graceful per-file error handling in Wave 1 pipeline fetchDriveMetadata, downloadDriveFiles, and uploadFilesToGemini now return partial results + an errors map instead of throwing on the first failure. runBatchAI chains the stages so only successfully processed files advance, and writes [File error: ...] directly to output cells for affected rows rather than aborting the whole chunk. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: harden Wave 1 error handling and restore single-flush invariant - uploadFilesToGemini: check getResponseCode() before JSON.parse, add try/catch for non-JSON bodies so every failure path sets the errors map - callGeminiAPIBatch: wrap JSON.parse in try/catch so one malformed response body cannot abort the entire batch - downloadDriveFiles: parse error body for actionable messages, matching fetchDriveMetadata behavior - index.ts: eliminate redundant uploadBytes copy (pass bytes directly), clear bytes map after upload to release memory before Wave 2, defer file-error cell writes to post-batch loop so the entire chunk lands in a single SpreadsheetApp.flush() - Toast now correctly counts file-error rows in the error tally Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * cleanup * test(client): add tests for getActiveRangeInfo service * test(server): add edge-case branch tests for Drive API calls * docs: add design and plan for coverage threshold fixes --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Three A/B test UX patterns for the document summarization recipe: V1 (4-button), V2 (2-button simplified), V3 (didactic step-by-step). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Manual QA
Notes